package io.xxx.eva.task;

import io.xxx.eva.config.IdGenerator;
import io.xxx.eva.task.job.ExecuteTaskJob;
import io.xxx.eva.task.request.AddTaskRequest;
import io.xxx.eva.task.request.GetTaskRequest;
import io.xxx.eva.task.request.UpdateTaskRequest;
import jakarta.annotation.Resource;
import org.quartz.*;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;

@Service
public class TaskService {

    @Resource
    private IdGenerator idGenerator;

    @Resource
    private TaskRepository taskRepository;

    @Resource
    private Scheduler scheduler;

    public long add(AddTaskRequest request) throws SchedulerException {
        Task task = new Task();
        BeanUtils.copyProperties(request, task);
        Long id = idGenerator.nextId();
        task.setId(id);
        LocalDateTime now = LocalDateTime.now();
        task.setCreatedTime(now);
        task.setUpdatedTime(now);
        taskRepository.save(task);

        JobDetail jobDetail = JobBuilder.newJob(ExecuteTaskJob.class)
                .withIdentity(getJobKey(id))
                .usingJobData("taskId", id)
                .build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("executeTaskTrigger-" + id)
                .build();
        scheduler.scheduleJob(jobDetail, trigger);
        return id;
    }

    public Page<Task> list(GetTaskRequest request, Pageable pageable) {
        Task task = new Task();
        BeanUtils.copyProperties(request, task);
        Example<Task> example = Example.of(task);
        return taskRepository.findAll(example, pageable);
    }

    public Optional<Task> get(long id) {
        return taskRepository.findById(id);
    }

    public void update(UpdateTaskRequest request) {
        Task task = new Task();
        BeanUtils.copyProperties(request, task);
        LocalDateTime now = LocalDateTime.now();
        task.setUpdatedTime(now);
        taskRepository.save(task);
    }

    public void delete(long id) throws SchedulerException {
        scheduler.deleteJob(getJobKey(id));
        taskRepository.deleteById(id);
    }

    public void cancel(long id) throws UnableToInterruptJobException {
        scheduler.interrupt(getJobKey(id));
        Optional<Task> taskOptional = taskRepository.findById(id);
        if (taskOptional.isEmpty()) {
            throw new RuntimeException("任务不存在");
        }
        Task task = taskOptional.get();
        task.setStatus(Task.Status.CANCELED);
        task.setUpdatedTime(LocalDateTime.now());
        taskRepository.save(task);
    }

    private JobKey getJobKey(long id) {
        return JobKey.jobKey("executeTaskJob-" + id);
    }
}
